Skip to content

feat(files): allow image uploads in workspace files#4419

Merged
waleedlatif1 merged 3 commits intostagingfrom
waleedlatif1/files-png-upload
May 3, 2026
Merged

feat(files): allow image uploads in workspace files#4419
waleedlatif1 merged 3 commits intostagingfrom
waleedlatif1/files-png-upload

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • workspace Files upload was rejecting all images (PNG, JPG, etc.) because the accept attribute had no image extensions, even though the backend accepts any file type
  • added SUPPORTED_IMAGE_EXTENSIONS (png, jpg, jpeg, gif, webp, svg, bmp, tif, tiff, heic, heif, avif, ico) and included it in the workspace files picker
  • consolidated the duplicate local image extension list previously used by CHAT_ACCEPT_ATTRIBUTE

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 3, 2026 9:43am

Request Review

@gitguardian
Copy link
Copy Markdown

gitguardian Bot commented May 3, 2026

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@cursor
Copy link
Copy Markdown

cursor Bot commented May 3, 2026

PR Summary

Low Risk
Low risk UI/validation-list change: expands the client-side accept filter and type filtering to include images, with no changes to upload/storage behavior.

Overview
Workspace Files now treats images as a first-class file type: the upload picker accept list includes common image extensions, file rows label image/* as “Image”, and the UI type filter adds an Images option.

Upload validation/attributes were updated by introducing SUPPORTED_IMAGE_EXTENSIONS in validation.ts and reusing it for CHAT_ACCEPT_ATTRIBUTE, eliminating the previous duplicated image-extension list.

Reviewed by Cursor Bugbot for commit 81f62ff. Configure here.

@waleedlatif1 waleedlatif1 force-pushed the waleedlatif1/files-png-upload branch from 1969271 to 277b344 Compare May 3, 2026 05:02
@waleedlatif1 waleedlatif1 force-pushed the waleedlatif1/files-png-upload branch from 277b344 to 143056c Compare May 3, 2026 05:03
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 3, 2026

Greptile Summary

This PR fixes a bug where workspace file uploads were silently rejecting all image files because the accept attribute had no image extensions. It introduces SUPPORTED_IMAGE_EXTENSIONS (13 formats), adds the corresponding SupportedImageExtension type, folds images into SupportedMediaExtension, expands SUPPORTED_IMAGE_MIME_TYPES with 7 additional MIME types, and wires up image filtering/labeling throughout the workspace files UI. The previously flagged SupportedMediaExtension omission and the narrow SUPPORTED_IMAGE_MIME_TYPES list are both resolved in this commit.

Confidence Score: 5/5

This PR is safe to merge — it fixes a clear bug with no regressions introduced.

All previously flagged issues (missing SupportedImageExtension in SupportedMediaExtension, narrow SUPPORTED_IMAGE_MIME_TYPES) are resolved. The logic changes are straightforward, limited to the file picker accept attribute and UI filter labels, and follow the same pattern used for audio/video.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/uploads/utils/validation.ts Adds SUPPORTED_IMAGE_EXTENSIONS constant and SupportedImageExtension type, folds it into SupportedMediaExtension, expands SUPPORTED_IMAGE_MIME_TYPES with 7 additional MIME types, and replaces the old local dot-prefixed extension list with a mapped reference to the new constant.
apps/sim/app/workspace/[workspaceId]/files/files.tsx Imports and spreads SUPPORTED_IMAGE_EXTENSIONS into the accept attribute array, adds image/ MIME-prefix check to formatFileType and the type filter, and adds an "Images" entry to the filter combobox and type label maps.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User opens workspace file picker] --> B[ACCEPT_ATTR built from SUPPORTED_EXTENSIONS]
    B --> C{File extension in list?}
    C -- "Yes (now includes images)" --> D[File accepted by browser picker]
    C -- "No" --> E[File hidden/rejected by browser]
    D --> F[File uploaded to backend]
    F --> G[formatFileType called]
    G --> H{mimeType check}
    H -- "starts with image/" --> I["Label: Image"]
    H -- "starts with audio/" --> J["Label: Audio"]
    H -- "starts with video/" --> K["Label: Video"]
    H -- "in MIME_TYPE_LABELS" --> L["Specific label: PDF, Word…"]
    F --> M[Type filter applied]
    M --> N{"typeFilter includes 'image'?"}
    N -- "Yes" --> O["f.type?.startsWith('image/')"]
    O -- true --> P[File shown in filtered view]
    O -- false --> Q[File hidden]
Loading

Reviews (4): Last reviewed commit: "fix(files): match all image mime types i..." | Re-trigger Greptile

@waleedlatif1 waleedlatif1 force-pushed the waleedlatif1/files-png-upload branch from 143056c to b72e737 Compare May 3, 2026 05:05
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/workspace/[workspaceId]/files/files.tsx
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/workspace/[workspaceId]/files/files.tsx
Comment thread apps/sim/app/workspace/[workspaceId]/files/files.tsx Outdated
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 81f62ff. Configure here.

@waleedlatif1 waleedlatif1 merged commit 14c93f6 into staging May 3, 2026
14 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/files-png-upload branch May 3, 2026 09:50
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile-apps Disagreeing with this one.

Looking at apps/sim/lib/uploads/utils/file-utils.ts:

  • isAudioFileTypegetContentType(mime) === 'audio' → MIME-map lookup
  • isVideoFileType → same
  • isImageFileType → MIME-set lookup

None of the three helpers do extension-based fallback — the claim that audio/video helpers fall back to extensions is incorrect.

A startsWith('image/') check is actually more permissive than a helper backed by MIME_TYPE_MAPPING would be — that map only includes 6 image MIME types, while this PR added 7 more (bmp/tiff/heic/heif/avif/ico). An isImageFileType helper based on the existing pattern would silently exclude exactly those new formats, which was the prior P1 we just fixed.

I deliberately didn't widen isImageFileType itself because it gates copilot upload + presigned-route auth paths where broadening allowed types would be an unintended scope expansion. Keeping the inline startsWith localizes the broader behavior to the UI filter where it's safe.

On the null-MIME concern: f.type here is WorkspaceFileRecord.type populated server-side at upload — it isn't null in practice. And the existing audio/video helpers would actually crash on a null MIME (.toLowerCase() on null), so the optional-chained startsWith is strictly safer than the helper pattern with respect to nullability.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 3, 2026

You're right on all counts — I was wrong about the extension fallback, and the deliberate scope isolation makes sense here. The inline startsWith('image/') is intentionally more permissive for the UI filter while keeping the helper's narrower MIME set intact for the auth/upload paths. And the optional-chained ?.startsWith being safer than the helper on null MIME is a fair point too.

Happy to defer to this approach.

Tip: You can give me more context with [.greptile/rules.md](https://www.greptile.com/docs/code-review/custom-standards) so I get this right next time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant